﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using AsterNET.FastAGI;
using AsterNET.FastAGI.Command;

namespace AsterNET.Extensions.FastAGI.Helpers
{
    /// <summary>
    /// This indicates the status of the execution of the VoiceMail application.
    /// </summary>
    public enum VMStatus
    {
        /// <summary>
        /// 
        /// </summary>
        Success,
        /// <summary>
        /// 
        /// </summary>
        UserExit,
        /// <summary>
        /// 
        /// </summary>
        Failed
    }

    /// <summary>
    /// 
    /// </summary>
    public class VoicemailOptions
    {
        /// <summary>
        /// The letter s, if present, causes the instructions ("Please leave your message after the tone. 
        /// When done, hang up, or press the pound key.") to be skipped.
        /// </summary>
        /// <returns></returns>
        public static string SkipInstructions()
        {
            return "s";
        }

        /// <summary>
        /// The letter u, if present, causes the unavailable message to be played. By default, the message says, 
        /// "The person at extension ... 1234 ... is unavailable," but the mailbox owner may record their own 
        /// unavailable message with the VoicemailMain command.
        /// </summary>
        /// <returns></returns>
        public static string Unavailable()
        {
            return "u";
        }

        /// <summary>
        /// The letter b, if present, causes the busy message to be played. By default, the message says, 
        /// "The person at extension ... 1234 ... is busy."
        /// </summary>
        /// <returns></returns>
        public static string Busy()
        {
            return "b";
        }

        /// <summary>
        /// (Only when specifying the flags as the second argument) Adjust the gain of the recording. 
        /// The # is an integer representing the amount of gain in decibels. 
        /// (This actually sets a channel option to increase the RX gain, this option is unfortunately only 
        /// supported on Zap, see the volgain voicemail.conf option to have asterisk call sox to adjust the 
        /// gain on voicemails sent as email attachements)
        /// </summary>
        /// <param name="gain"></param>
        /// <returns></returns>
        public static string AdjustGain(int gain)
        {
            return string.Format("g({0})", gain.ToString());
        }
    }

    /// <summary>
    /// 
    /// </summary>
    public class VoicemailHelper
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="mailbox"></param>
        /// <returns></returns>
        public static ExecCommand Voicemail(string mailbox)
        {
            return Voicemail(mailbox, "");
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="mailbox"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        public static ExecCommand Voicemail(string mailbox, string context)
        {
            return Voicemail(mailbox, context, new string[] {});
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="mailbox"></param>
        /// <param name="flags"></param>
        /// <returns></returns>
        public static ExecCommand Voicemail(string mailbox, params string[] flags)
        {
            return Voicemail(mailbox, null, flags);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="mailbox"></param>
        /// <param name="context"></param>
        /// <param name="flags"></param>
        /// <returns></returns>
        public static ExecCommand Voicemail(string mailbox, string context, params string[] flags)
        {
            string rtn;
            if(!string.IsNullOrEmpty(context))
                rtn = string.Format("{0}@{1},{2}",
                mailbox, context, String.Join(",", flags));
            else
                rtn = string.Format("{0},{1}",
                mailbox, String.Join(",", flags));

            return new ExecCommand("Voicemail", rtn);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="channel"></param>
        /// <param name="mailbox"></param>
        /// <returns></returns>
        public static VMStatus Voicemail(AGIChannel channel, string mailbox)
        {
            return Voicemail(channel, mailbox, "");
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="channel"></param>
        /// <param name="mailbox"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        public static VMStatus Voicemail(AGIChannel channel, string mailbox, string context)
        {
            return Voicemail(channel, mailbox, context, new string[] { });
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="channel"></param>
        /// <param name="mailbox"></param>
        /// <param name="flags"></param>
        /// <returns></returns>
        public static VMStatus Voicemail(AGIChannel channel, string mailbox, params string[] flags)
        {
            return Voicemail(channel, mailbox, null, flags);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="channel"></param>
        /// <param name="mailbox"></param>
        /// <param name="context"></param>
        /// <param name="flags"></param>
        /// <returns></returns>
        public static VMStatus Voicemail(AGIChannel channel, string mailbox, string context, params string[] flags)
        {
            string rtn;
            if (!string.IsNullOrEmpty(context))
                rtn = string.Format("{0}@{1},{2}",
                mailbox, context, String.Join(",", flags));
            else
                rtn = string.Format("{0},{1}",
                mailbox, String.Join(",", flags));

            channel.SendCommand(new ExecCommand("Voicemail", rtn));

            channel.SendCommand(new GetVariableCommand("VMSTATUS"));
            return (VMStatus)Enum.Parse(typeof(VMStatus), channel.LastReply.Extra, false);

        }
    }
}
